import { getPageConfig, getGuid } from '@/utils/common';
import Vue from 'vue';

function updateData(target, path, value) {
    path.split('.').reduce((total, curVal, curIndex, arr) => {
        if (curIndex === arr.length - 1) {
            if (total[curVal] === undefined) {
                Vue.set(total, curVal, value);
            } else {
                total[curVal] = value;
            }
            
        }
        if (total[curVal] === undefined) {
            if (/\d/.test(curVal)) {
                Vue.set(total, arr[curIndex - 1], []);
            } else {
                Vue.set(total, curVal, {});
            }
        }
        return total[curVal];
    } , target);
}

const NEW_SCENE = 'NEW_SCENE';
const DELETE_SCENE = 'DELETE_SCENE';

const UPDATE_PAGE = 'UPDATE_PAGE';

const ADD_COMPONENT = 'ADD_COMPONENT';
const UPDATE_COMPONENT = 'UPDATE_COMPONENT';
const DELETE_COMPONENT = 'DELETE_COMPONENT';

const ADD_STATUS = 'ADD_STATUS';
const REMOVE_STATUS = 'REMOVE_STATUS';

const CREATE_TWEEN = 'CREATE_TWEEN';
const DELETE_TWEEN = 'DELETE_TWEEN';
const SWITCH_PAGE = 'SWITCH_PAGE';
const SWITCH_MARK = 'SWITCH_MARK';
const SWITCH_STATUS = 'SWITCH_STATUS';


function createState() {
    const firstPage = getPageConfig();
    return {
        config: {
            selector: '#screen',
            fps: 30,
            scale: 1,
            width: 512,
            height: 288,
            params: [],
            apis: [],
            value: {},
            pages: [firstPage]
        },
        pageIndex: firstPage.mark,
        mark: '',
        status: '',
    };
};

const mutations = {
    RESET_CONFIG(state, data) {
        const firstPage = getPageConfig();
        state.config = {
            selector: '#screen',
            fps: 30,
            scale: 1,
            width: 512,
            height: 288,
            params: [],
            apis: [],
            value: {},
            pages: [firstPage]
        };
        state.pageIndex = firstPage.mark;
        state.mark = '';
        state.status = '';
    },
    SET_CONFIG(state, data) {
        state.config = data;
        if (data.pages.length > 0) {
            state.pageIndex = data.pages[0].mark;
        }
        state.mark = '';
        state.status = '';
    },
    /**
     * 新建场景页
     * @param {*} state 
     * @param {*} data 
     */
    [NEW_SCENE](state, data) {
        const { pages = [] } = state.config;
        const page = getPageConfig();
        pages.push(page);
        state.pageIndex = page.mark;
        state.mark = '';
        state.status = '';
    },
    /**
     * 删除场景页
     * @param {*} state 
     * @param {*} data 
     */
    [DELETE_SCENE](state, data) {
        const { mark } = data;
        const { pageIndex: currentPageMark } = state;
        console.log('delete mark', mark)
        const { pages = [] } = state.config;
        const pageIndex = pages.findIndex(vo => vo.mark === mark);
        if (pageIndex >= 0) {
            pages.splice(pageIndex, 1);
            if (currentPageMark === mark) {
                if (pageIndex >= 1) {
                    state.pageIndex = pages[pageIndex - 1].mark;
                } else {
                    state.pageIndex = pages[pageIndex + 1].mark;
                }
            }
        }
    },
    /**
     * 切换关键帧
     * @param {*} state 
     * @param {*} data 
     */
    [SWITCH_STATUS](state, data) {
        const { pageIndex, config } = state;
        const page = config.pages.find(vo => vo.mark === pageIndex);
        const { mark, status } = data;
        const { components = [] } = page;
        const componentIndex = components.findIndex(vo => vo.mark === mark);
        if (componentIndex >= 0) {
            const component = components[componentIndex];
            component.curStatus = status;
        }
        state.mark = mark;
    },
    /**
     * 切换组件
     * @param {*} state 
     * @param {*} data 
     */
    [SWITCH_MARK](state, data) {
        const { mark } = data;
        state.mark = mark;
    },
    /**
     * 切换场景
     * @param {*} state 
     * @param {*} data 
     */
    [SWITCH_PAGE](state, data) {
        const { pageIndex } = data;
        console.log('change page==>', pageIndex);
        state.pageIndex = pageIndex;
    },
    /**
     * 添加组件
     * @param {*} state 
     * @param {*} data 
     */
    [ADD_COMPONENT](state, data) {
        const { config, pageIndex } = state;
        const { pages = [] } = config;
        const mark = getGuid();
        const page = pages.find(vo => vo.mark === pageIndex);
        const component = {
            mark,
            name: data.name,
            curStatus: data.statusId,
            view: true,
            data: data.data,
            status: [{
                id: data.statusId,
                timer: data.tick || 0,
                style: data.style,
            }],
            tweens: [],
            // tweens: [{
            //     startId: statusId,
            //     endId: statusId,
            //     func: 'linear',
            //     id: getGuid(),
            // }],
            animations: data.animations !== undefined ? data.animations : [],
        };
        
        page.components.push(component);
        state.mark = mark;
    },
    /**
     * 修改组件事否可见
     * @param {*} state 
     * @param {*} data 
     */
    SWITCH_VIEW(state, data) {
        const { config, pageIndex } = state;
        const { mark, view } = data;
        const { pages = [] } = config;
        const page = pages.find(vo => vo.mark === pageIndex);
        if (page) {
            const { components = [] } = page;
            const component = components.find(vo => vo.mark === mark);
            if (component) {
                Vue.set(component, 'view', view);
            }
        }  
    },
    /**
     * 修改组件中文名称
     * @param {*} state 
     * @param {*} data 
     */
    CHANGE_NAME(state, data) {
        const { config, pageIndex } = state;
        const { mark, name } = data;
        const { pages = [] } = config;
        const page = pages.find(vo => vo.mark === pageIndex);
        if (page) {
            const { components = [] } = page;
            const component = components.find(vo => vo.mark === mark);
            if (component) {
                Vue.set(component, 'zh_name', name);
            }
        }
    },
    /**
     * 更新组件
     * @param {*}} state 
     * @param {*} data 
     */ 
    [UPDATE_COMPONENT](state, data) {
        const { pageIndex, mark, config } = state;
        const { changes } = data;
        const page = config.pages.find(vo => vo.mark === pageIndex);
        const { components = [] } = page;
        const componentIndex = components.findIndex(vo => vo.mark === mark);
        if (componentIndex >= 0) {
            const component = components[componentIndex];
            for (let i = 0; i < changes.length; i++) {
                const change = changes[i];
                const { path, value } = change;
                if (/^style/.test(path)) {
                    const { curStatus, status = [] } = component;
                    const curIndex = status.findIndex(vo => vo.id === curStatus);
                    if (curIndex >= 0) {
                        const targetPath = `status.${curIndex}.${path}`;
                        updateData(component, targetPath, value);
                    }
                } else {
                    updateData(component, path, value);
                }
            }
        }
    },
    /**
     * 更新页面内容
     */
    [UPDATE_PAGE](state, data) {
        const { pageIndex, config } = state;
        const { changes = [] } = data;
        const page = config.pages.find(vo => vo.mark === pageIndex);
        for (let i = 0; i < changes.length; i++) {
            const change = changes[i];
            const { path, value } = change;
            updateData(page, path, value);
        }
    },
    /**
     * 删除组件
     * @param {*} state 
     * @param {*} data 
     */
    [DELETE_COMPONENT](state, data) {

    },
    /**
     * 添加关键帧
     * @param {*} state 
     * @param {*} data 
     */
    [ADD_STATUS](state, data) {
        const { component, status } = data;
        const { pageIndex,  config } = state;
        const page = config.pages.find(vo => vo.mark === pageIndex);
        const { components = [] } = page;
        const componentIndex = components.findIndex(vo => vo.mark === component);
        if (componentIndex >= 0) {
            const comp = components[componentIndex];
            const id = getGuid();
            status.id = id;
            comp.curStatus = id;
            comp.status.push(status);
            state.mark = component;
        }
    },
    /**
     * 添加关键帧
     * @param {*} state 
     * @param {*} data 
     */
    ADD_FRAME(state, data) {
        const { mark, timer, style, id } = data;
        const { pageIndex, config } = state;
        const page = config.pages.find(vo => vo.mark === pageIndex);
        const { components = [] } = page;
        const component = components.find(vo => vo.mark === mark);
        if (component) {
            const { tweens = [], status = [] } = component;
            status.push({
                id,
                timer,
                style,
            });
            Vue.set(component, 'status', status);
            // 判断当前时间内是否存在补间动画
            let targetTween = null;
            let targetTweenStart = null;
            let targetTweenEnd = null;
            let targetTweenIndex = -1;
            for (let i = 0; i < tweens.length; i++) {
                const tween = tweens[i];
                const { startId, endId } = tween;
                const startFrame = status.find(vo => vo.id === startId);
                const endFrame = status.find(vo => vo.id === endId);
                if (startFrame.timer < timer && timer < endFrame.timer) {
                    targetTween = tween;
                    targetTweenStart = startFrame;
                    targetTweenEnd = endFrame;
                    targetTweenIndex = i;
                    break;
                }
            }
            component.curStatus = id;
            if (targetTween) {
                // 删除原补间动画， 增加新的两段补间动画
                tweens.splice(targetTweenIndex, 1);
                tweens.push({
                    startId: targetTweenStart.id,
                    endId: id,
                    func: targetTween.func,
                    id: getGuid(),
                });
                tweens.push({
                    startId: id,
                    endId: targetTweenEnd.id,
                    func: targetTween.func,
                    id: getGuid(),
                });
            }
        }
    },
    /**
     * 删除关键帧
     * @param {*} state 
     * @param {*} data 
     */
    [REMOVE_STATUS](state, data) {
        const { status: statusId, mark } = data;
        const { pageIndex, config } = state;
        const page = config.pages.find(vo => vo.mark === pageIndex);
        const { components = [] } = page;
        const componentIndex = components.findIndex(vo => vo.mark === mark);
        if (componentIndex >= 0) {
            const comp = components[componentIndex];
            const { status = [], tweens = [] } = comp;
            const statusIndex = status.findIndex(vo => vo.id === statusId);
            if (statusIndex >= 0) {
                // 校验是否存在补间动画，存在则删除
                const tween = tweens.filter(vo => vo.startId === status[statusIndex].id || vo.endId === status[statusIndex].id);
                if (tween) {
                    if(tween.length === 1) {
                        const tweenIndex = tweens.findIndex(vo => vo.id === tween[0].id);
                        tweens.splice(tweenIndex, 1);
                    } else {
                        let startId = -1, endId = -1;
                        if (tween[0].startId === status[statusIndex].id) {
                            endId = tween[0].endId;
                            startId = tween[1].startId;
                        } else {
                            startId = tween[0].startId;
                            endId = tween[1].endId;
                        }
                        for (let i = 0; i < tween.length; i++) {
                            const targetTweenIndex = tweens.findIndex(vo => vo.id === tween[i].id);
                            tweens.splice(targetTweenIndex, 1);
                        }
                        tweens.push({
                            startId,
                            endId,
                            func: 'linear',
                            id: getGuid(),
                        });
                    }
                }
                status.splice(statusIndex, 1);
            }
            if (statusId === comp.curStatus) {
                comp.curStatus = status[0].id;
            }
        }
    },
    /**
     * 创建补间动画
     * @param {*} state 
     * @param {*} data 
     */
    [CREATE_TWEEN](state, data) {
        const { mark, startId, endId, func } = data;
        const { pageIndex,  config } = state;
        const page = config.pages.find(vo => vo.mark === pageIndex);
        const { components = [] } = page;
        const componentIndex = components.findIndex(vo => vo.mark === mark);
        if (componentIndex >= 0) {
            const comp = components[componentIndex];
            comp.tweens.push({
                startId,
                endId,
                func,
                id: getGuid(),
            });
        }
    },
    /**
     * 删除补间动画
     * @param {*}} state 
     * @param {*} data 
     */
    [DELETE_TWEEN](state, data) {
        const { tweenId, mark } = data;
        const { pageIndex, config } = state;
        const page = config.pages.find(vo => vo.mark === pageIndex);
        const { components = [] } = page;
        const componentIndex = components.findIndex(vo => vo.mark === mark);
        if (componentIndex >= 0) {
            const comp = components[componentIndex];
            const { tweens = [] } = comp;
            const tweenIndex = tweens.findIndex(vo => vo.id === tweenId);
            if (tweenIndex >= 0) {
                tweens.splice(tweenIndex, 1);
            }
        }
    },
    /**
     * 更改当前所有的当前帧
     * @param {*} state 
     * @param {*} data 
     */
    SWITCH_ALL_FRAME(state, data) {
        const { pageIndex, config } = state;
        const page = config.pages.find(vo => vo.mark === pageIndex);
        if (page) {
            const { components = [] } = page;
            for (let i = 0; i < components.length; i++) {
                const component = components[i];
                const { status = [] } = component;
                let maxFrameTimer = -1;
                let targetStatus = '';
                for (let j = 0; j < status.length; j++) {
                    const frame = status[j];
                    if (frame.timer < data && frame.timer > maxFrameTimer) {
                        maxFrameTimer = frame.timer;
                        targetStatus = frame.id;
                    }
                }
                component.curStatus = targetStatus;
            }
        }
    },
    /**
     * 设置动画缓动函数
     * @param {*} state 
     * @param {*} data 
     */
    SET_EASE(state, data) {
        const { pageIndex, config } = state;
        const { mark, tweenId, func } = data;
        const page = config.pages.find(vo => vo.mark === pageIndex);
        if (page) {
            const { components = [] } = page;
            const component = components.find(vo => vo.mark === mark);
            const { tweens = [] } = component;
            const tween = tweens.find(vo => vo.id === tweenId);
            if (tween) {
                tween.func = func;
            }
        }
    }
};

const actions = {

};

const getters = {

};

export default {
    state: createState,
    mutations,
    actions,
    getters,
};